import 'dart:async';

import 'package:flutter/material.dart';

class StreamPage extends StatefulWidget {
  final Map<String, dynamic> arguments;
  StreamPage({Key key, this.arguments}) : super(key: key);

  @override
  _StreamPageState createState() => _StreamPageState();
}

class _StreamPageState extends State<StreamPage> {
  //
  StreamSubscription _subscription0;

  //
  StreamController<String> _streamController;
  StreamSubscription _subscription1;
  StreamSink _streamSink;

  //
  StreamController<String> _streamController2;
  StreamSubscription _subscription2;

  @override
  void initState() {
    super.initState();

    // 1 -
    (() {
      onData(String data) {
        print(data);
      }

      onError(error) {
        print(error);
      }

      onDone() {
        print('Done');
      }

      Stream<String> _stream = Stream.fromFuture(this._fetchData('orange'));
      this._subscription0 = _stream.listen(onData, onError: onError, onDone: onDone);
    })();

    // 2 -
    (() {
      onData(String data) {
        print(data);
      }

      onError(error) {
        print(error);
      }

      onDone() {
        print('Done');
      }

      this._streamController = StreamController<String>();
      this._streamSink = _streamController.sink;
      this._subscription1 = _streamController.stream.listen(onData, onError: onError, onDone: onDone);
    })();

    // 3 -
    (() {
      onData20(String data) {
        print('onData0: ' + data);
      }

      onData21(String data) {
        print('onData1: ' + data);
      }

      onError(error) {
        print(error);
      }

      onDone() {
        print('Done');
      }

      this._streamController2 = StreamController.broadcast();
      this._subscription2 = _streamController2.stream.listen(onData20, onError: onError, onDone: onDone);
      this._subscription2 = _streamController2.stream.listen(onData21, onError: onError, onDone: onDone);
    })();
  }

  @override
  void dispose() {
    //
    if (_subscription0 != null) {
      _subscription0.cancel();
    }

    //
    if (_streamController != null) {
      _streamController.close();
    }
    if (_subscription1 != null) {
      _subscription1.cancel();
    }
    if (_streamSink != null) {
      _streamSink.close();
    }

    //
    if (_streamController2 != null) {
      _streamController2.close();
    }
    if (_subscription2 != null) {
      _subscription2.cancel();
    }

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('StreamPage'),
      ),
      body: ListView(
        children: <Widget>[
          ListTile(
            title: Text('Conception'),
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Text('''
- 管道;
- 可以传递任何类型数据;
- Stream 类型: 单订阅 & 多订阅
- 适时释放 Resources:
  StreamSubscription.cancel();
  StreamController.close();
                  '''),
                )
              ],
            ),
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('''
1
- Stream<T>
- StreamSubscription<T>
'''),
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Text('''
- Stream
  Stream<String> _stream = Stream.fromFuture(fetchData());
  _stream.listen(onData, onError: onError, onDone: onDone);

- StreamSubscription
  pause
  cancel (取消后无法恢复)
  resume
  '''),
                ),
                Row(
                  children: <Widget>[
                    RaisedButton(
                      child: Text('pause'),
                      onPressed: () {
                        this._subscription0.pause();
                      },
                    ),
                    RaisedButton(
                      child: Text('resume'),
                      onPressed: () {
                        this._subscription0.resume();
                      },
                    ),
                    RaisedButton(
                      child: Text('cancel'),
                      onPressed: () {
                        this._subscription0.cancel();
                      },
                    ),
                  ],
                ),
              ],
            ),
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('''
2
- StreamController<T>
- StreamSink<S>
'''),
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Text('''
- StreamController 控制和管理 Stream;
- void add(T event);
- Future close();
- resume 后, 输出 pause 过程中添加的数据;
'''),
                ),
                Row(
                  children: <Widget>[
                    RaisedButton(
                      child: Text('add'),
                      onPressed: () {
                        addEventToStream() async {
                          String data = await _fetchData('banana');

                          // 使用 StreamController 添加
                          // this._streamController.add(data);

                          // 使用 StreamSink 添加
                          this._streamSink.add(data);
                        }

                        addEventToStream();
                      },
                    ),
                    RaisedButton(
                      child: Text('pause'),
                      onPressed: () {
                        this._subscription1.pause();
                      },
                    ),
                    RaisedButton(
                      child: Text('resume'),
                      onPressed: () {
                        this._subscription1.resume();
                      },
                    ),
                  ],
                ),
              ],
            ),
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('''
3
- 多订阅 StreamController.broadcast()
- StreamBuilder: 监听到数据改变时自动重建
'''),
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Text('''
- 添加多个订阅, 每个订阅可单独决定使用 Stream 上的数据;
                  '''),
                ),
                StreamBuilder(
                  stream: this._streamController2.stream,
                  initialData: '...',
                  builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
                    return Text('StreamBuilder data: ' + snapshot.data);
                  },
                ),
                Row(
                  children: <Widget>[
                    RaisedButton(
                      child: Text('add'),
                      onPressed: () {
                        addEventToStream() async {
                          String data = await _fetchData('apple');
                          this._streamController2.add(data);
                        }

                        addEventToStream();
                      },
                    ),
                  ],
                )
              ],
            ),
          ),
        ],
      ),
    );
  }

  onData(String data) {
    print(data);
  }

  onData0(String data) {
    print(data);
  }

  onData20(String data) {
    print(data);
  }

  onData21(String data) {
    print(data);
  }

  Future<String> _fetchData(String name) async {
    await Future.delayed(Duration(seconds: 2));
    // throw 'throw error';
    return '_fetchData: ' + name;
  }
}
